package com.aaa.util;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.sql.*;
import java.util.*;

public class BaseDao<T> {

   private static DataSource ds;

   static {

       // 1.加载配置文件
       Properties properties = new Properties();
       try {
           properties.load(BaseDao.class.getClassLoader().getResourceAsStream("druid.properties"));
            // 获取连接池
           ds = DruidDataSourceFactory.createDataSource(properties);
       } catch (IOException e) {
           e.printStackTrace();
       } catch (Exception e) {
           e.printStackTrace();
       }

   }

    /**
     * 单例
     */
    private BaseDao(){}

    private static class SingleTonHoler{
        private static BaseDao INSTANCE = new BaseDao();
    }

    public static BaseDao getInstance(){
        return SingleTonHoler.INSTANCE;
    }


    /**
     * 获取连接
     * @return
     */
    private Connection getConnection(){

        Connection connection = null;

        try {
            connection = ds.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }


        return connection ;
    }


    /**
     * 增删 改
     * @param sql
     * @param params
     * @return
     */
    public int  executeUpdate(String sql, Object[] params){
        int len = -1;

        Connection connection = getConnection();
        PreparedStatement preparedStatement = null;

        try {
            preparedStatement = connection.prepareStatement(sql);

            if (params!=null){

                for (int i =0;i<params.length;i++){
                    // 注意 parameterIndex 从下标 1 开始
                    preparedStatement.setObject(i+1,params[i]);
                }
            }

            len =    preparedStatement.executeUpdate();

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            // 释放资源
            closeAll(connection, preparedStatement);

        }

        return len;
    }


    /**
     * 增删 改
     * @param sql
     * @param params
     * @return
     */
    public int  executeInsert(String sql, Object[] params){
        int id = 0;

        Connection connection = getConnection();
        PreparedStatement preparedStatement = null;

        try {
            preparedStatement = connection.prepareStatement(sql);

            if (params!=null){

                for (int i =0;i<params.length;i++){
                    // 注意 parameterIndex 从下标 1 开始
                    preparedStatement.setObject(i+1,params[i]);
                }
            }

            preparedStatement.executeUpdate();

            ResultSet rst = preparedStatement.getGeneratedKeys();
            if(rst.next()) {
                id = rst.getInt(1);
                System.out.print("获取自动增加的id号=="+id+"\n");
            }


        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            // 释放资源
            closeAll(connection, preparedStatement);

        }

        return id;
    }



    /**
     * 通用查询
     * @param sql
     * @param params
     * @return
     */
    public List<Map<String, Object>> query(String sql, Object[] params) {

        Connection connection = getConnection();

        PreparedStatement preparedStatement = null;

        // 放☞结果
        List<Map<String,Object>>resultList = new ArrayList<>();

        try {

            // 3.获取PreparedStatement
            preparedStatement = connection.prepareStatement(sql);

            if (params!=null){
                for (int i=0;i<params.length;i++){
                    preparedStatement.setObject(i+1, params[i]);

                }
            }

            // 4.执行sql语句

            ResultSet resultSet = preparedStatement.executeQuery();

            // 获取元数据  获取列名  列名对应类型
            ResultSetMetaData resultSetMetaData =  resultSet.getMetaData();

            // 获取列的数量
            int columnCount =   resultSetMetaData.getColumnCount();

            for (int i=0;i<columnCount;i++){
                // 获取列名
                String columnName =    resultSetMetaData.getColumnName(i+1);
                // 获取列对应的类型
                String columnClassName  = resultSetMetaData.getColumnClassName(i+1);

                System.out.println("columnName:"+columnName+"--columnClassName:"+columnClassName);
            }



            while (resultSet.next()) {

                HashMap<String,Object> map = new HashMap<>();
                // 获取一行数据
                for (int i=0;i<columnCount;i++){

                    String columnName =    resultSetMetaData.getColumnName(i+1);
                    Object object =   resultSet.getObject(i+1);

                    map.put(columnName,object);
//                    System.out.print(columnName+":"+object+"----");
                }
//                System.out.println("-------");
                resultList.add(map);
            }


        }  catch (SQLException e) {
            e.printStackTrace();
        } finally {

            // 5.释放资源，关闭连接

            closeAll(connection, preparedStatement);
        }


        return resultList;
    }

    /**
     * 获取根据实体类查询
     * @param sql
     * @param params
     * @param clazz
     * @return
     */
    public List<T> query(String sql,Object[] params,Class<?> clazz){
        List<T> resultList = new ArrayList<>();

        Connection connection = getConnection();

        PreparedStatement preparedStatement = null;


        try {

            // 3.获取PreparedStatement
            preparedStatement = connection.prepareStatement(sql);

            if (params!=null){
                for (int i=0;i<params.length;i++){
                    preparedStatement.setObject(i+1, params[i]);

                }
            }

            // 4.执行sql语句

            ResultSet resultSet = preparedStatement.executeQuery();

            // 获取元数据  获取列名  列名对应类型
            ResultSetMetaData resultSetMetaData =  resultSet.getMetaData();

            // 获取列的数量
            int columnCount =   resultSetMetaData.getColumnCount();

            String fieldName = "";
            Field field = null;

            while (resultSet.next()) {

                T obj = (T) clazz.newInstance();
                // 获取一行数据
                for (int i=0;i<columnCount;i++){

                     fieldName =    resultSetMetaData.getColumnName(i+1);

                    try {
                        field = clazz.getDeclaredField(fieldName);
                        field.setAccessible(true);
                        field.set(obj,convert(resultSet.getString(i+1),field.getType()));
                    } catch (NoSuchFieldException e) {
                        e.printStackTrace();
                    }
                }

                resultList.add(obj);
            }


        }  catch (SQLException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } finally {

            // 5.释放资源，关闭连接

            closeAll(connection, preparedStatement);
        }


        return resultList;

    }


    private void closeAll(Connection connection, PreparedStatement preparedStatement) {
        try {
            if (preparedStatement != null) {
                preparedStatement.close();
            }

            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }


    private <T extends Serializable> T convert(String param, Class<?> clas) {
        if (param == null || param == "" || clas == null) {
            return null;
        }
        String type = clas.getName();
        if (type.equals("java.lang.String")) {
            return (T) param;
        }
        try {
            if (type.equals("java.util.Date")) {
                return (T) new java.util.Date(Timestamp.valueOf(param).getTime());
            }
            if (type.equals("java.sql.Date")) {
                return (T) new java.sql.Date(Timestamp.valueOf(param).getTime());
            }
            if (type.equals("java.sql.Timestamp")) {
                return (T) Timestamp.valueOf(param);
            }
            if (type.equals("java.lang.Char")) {
                return (T) Character.valueOf(param.charAt(0));
            }
            if (type.equals("java.lang.Integer") || type.equals("int")) {
                return (T) Integer.valueOf(param);
            }
            if (type.equals("java.lang.Double") || type.equals("double")) {
                return (T) Double.valueOf(param);
            }
            if (type.equals("java.lang.Float") || type.equals("float")) {
                return (T) Float.valueOf(param);
            }
            if (type.equals("java.lang.Byte") || type.equals("byte")) {
                return (T) Byte.valueOf(param);
            }
            if (type.equals("java.lang.Short") || type.equals("short")) {
                return (T) Short.valueOf(param);
            }
            if (type.equals("java.lang.Long") || type.equals("long")) {
                return (T) Long.valueOf(param);
            }
            if (type.equals("java.lang.Boolean") || type.equals("boolean")) {
                return (T) Boolean.valueOf(param);
            }
        } catch (Exception e) {

        }
        return null;
    }


}
